// Copyright (c) 2023 Institute of Software, Chinese Academy of Sciences
// Ripple is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
package ripple.test;

import java.io.FileWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;

public class Main {
//     private static final int SERVER_COUNT = 3;
//     private static final int CLIENTS_PER_SERVER = 2;
//     private static final String DATABASE_PATH = "D:\\ripple-test-dir";

//     private static final int MAX_SERVER_COuNT = 100000;
    private static int SERVER_COUNT = 8;
    private static int CLIENTS_PER_SERVER = 100;
    private static String DATABASE_PATH = "data";

    private static int FAILURENUM = 0;

    public static void main(String[] args) throws Exception {

        for (UUID uuid : new HashSet<UUID>()) {
            System.err.println("");
        }

        // String s1 = "server-1.db";
        // String s2 = "server-2.db";
        // String s3 = "server-3.db";
        // String s4 = "server-4.db";
        // String s5 = "server-5.db";
        // String s6 = "server-6.db";
        // String s7 = "server-7.db";
        // String s8 = "server-8.db";
        // Set<String> set = new HashSet<>();
        // set.add(s8);
        // set.add(s7);
        // set.add(s6);
        // set.add(s5);
        // set.add(s4);
        // set.add(s3);
        // set.add(s2);
        // set.add(s1);
        // // System.out.println("for (String s : set) ");
        // // for (String s : set) {
        // //     System.out.println(s);
        // // }
        // List<String> list = Analyse.getSortedList(set);
        // System.out.println("for (String s : list) ");
        // for (String s : list) {
        //     System.out.println(s);
        // }
        // System.out.println("for (int i = 0; i < list.size(); i++)");
        // for (int i = 0; i < list.size(); i++) {
        //     System.out.println(list.get(i));
        // }
        // <NodeMetadata> nodeList = new ArrayList<>();
        // File debugDir = new File("debug");
        // DebugTool.prepareDir(debugDir);
        // nodeList.add(new NodeMetadata(1, "address 1", 1));
        // nodeList.add(new NodeMetadata(2, "address 2", 2));
        // nodeList.add(new NodeMetadata(3, "address 3", 3));
        // DebugTool.addNodeList(nodeList);
        // DebugTool.addNodeList(nodeList);
        // nodeList = DebugTool.getNodeList();
        // System.out.println(NodeMetadata.ListToString(nodeList));
        // TestVectorOverlay.run(SERVER_COUNT, CLIENTS_PER_SERVER, DATABASE_PATH, 3, FAILURENUM);
        //    TestTreeOverlay.run(SERVER_COUNT, CLIENTS_PER_SERVER, DATABASE_PATH);
        // Main.record();
        //        System.out.println("man what can i say 6");
        //        // FileWriter fileWriter = new FileWriter("Hello.txt");
        //        // fileWriter.write("Test Hello run\n");
        //        // fileWriter.write("Test Hello run1\n");
        //        // fileWriter.close();
        //        String storageLocation = "data";
        //        int id = 1;
        //
        //        ProcessBuilder pb = new ProcessBuilder("java",
        //                "@/tmp/cp_u0pc111uhmptm668ezj50qb8.argfile",
        //                "ripple.test.tools.RippleServerProcess");
        //        //启动进程
        //        Process p = pb.start();
        //
        //        OutputStream ops = p.getOutputStream();
        //        ops.write("data".getBytes());
        //        InputStream in = p.getInputStream();
        //        BufferedReader bfr = new BufferedReader(new InputStreamReader(in));
        //        String rd = bfr.readLine();
        //        if (rd != null) {
        //            System.out.println("From process" + rd);//输出子进程返回信息(即子进程中的System.out.println()内容)
        //        } else {
        //            return;
        //        }
        // p.destroy();
        // Process p2 = Runtime.getRuntime().exec("java com.test.process.pipe.MyTest");
        // TestOut out2 = new TestOut(p2, "-Hello-everyone".getBytes());
        // new Thread(out2).start();
        // TestIn ti2 = new TestIn(p2);
        // new Thread(ti2).start();
        // p.destroy();
        // String name = ManagementFactory.getRuntimeMXBean().getName();
        // System.out.println(name);
        // String pid = name.split("@")[0];
        // System.out.println("Pid is:" + pid);
        // System.in.read();
        // SERVER_COUNT -= (SERVER_COUNT * FAILURERATE + 99) / 100;
        // TryTestStarOverlay.run(SERVER_COUNT, CLIENTS_PER_SERVER, DATABASE_PATH);
        // TestTreeOverlay.run(SERVER_COUNT, CLIENTS_PER_SERVER, DATABASE_PATH);
        //        TestReform.run(SERVER_COUNT, CLIENTS_PER_SERVER, DATABASE_PATH);
        // TestHashingBasedOverlay.run(SERVER_COUNT, CLIENTS_PER_SERVER, DATABASE_PATH);
        // TestFailureStarOverlay.run(SERVER_COUNT, CLIENTS_PER_SERVER, DATABASE_PATH, FAILURERATE);
        // TestFailureTreeOverlay.run(SERVER_COUNT, CLIENTS_PER_SERVER, DATABASE_PATH, FAILURERATE);
        // TestTreeOverlay.run(SERVER_COUNT, CLIENTS_PER_SERVER, DATABASE_PATH);
        //  / Main.record();
    }

    public static void record() throws Exception {
        // String topic = "test topic";
        // List<Integer> latecyList = new ArrayList<>();
        // FileWriter fileWriter = new FileWriter("data/debug.txt");
        // for (int i = 0; i < SERVER_COUNT; i++) {
        //     String filename = DATABASE_PATH + "/server-" + (i + 1) + ".db";
        //     Connection connection = DriverManager.getConnection("jdbc:sqlite:" + filename);
        //     String sql = "SELECT * FROM [MQmessage] WHERE [topic] = ?;";
        //     PreparedStatement statement = connection.prepareStatement(sql);
        //     statement.setString(1, topic);
        //     ResultSet resultSet = statement.executeQuery();

        //         while (resultSet.next()) {
        //             // latecyList.add(resultSet.getInt("last_update"));
        //             int latecy = resultSet.getInt("latecy");
        //             if (latecy > 0) {
        //                 latecyList.add(latecy);
        //             } else {
        //                 fileWriter.write("Server: " + (i + 1) + ", Client: " + (j + 1) +
        //                 ", last_update: " + resultSet.getLong("last_update") + 
        //                 ", receive_time: " + resultSet.getLong("receive_time") + "\n");
        //             }
        //         }
        //         resultSet.close();
        // }
        // fileWriter.close();
        String applicationName = "testApp";

        String key = "test";
        List<Integer> latecyList = new ArrayList<>();
        FileWriter fileWriter = new FileWriter("data/debug.txt");
        for (int i = 0; i < SERVER_COUNT; i++) {
            String filename = DATABASE_PATH + "/server-" + (i + 1) + ".db";
            Connection connection = DriverManager.getConnection("jdbc:sqlite:" + filename);
            String sql = "SELECT * FROM [message] WHERE [item_application_name] = ? AND [item_key] = ?;";
            PreparedStatement statement = connection.prepareStatement(sql);
            statement.setString(1, applicationName);
            statement.setString(2, key);
            ResultSet resultSet = statement.executeQuery();

            while (resultSet.next()) {
                // latecyList.add(resultSet.getInt("last_update"));
                int latecy = resultSet.getInt("latecy");
                if (latecy > 0) {
                    latecyList.add(latecy);
                    fileWriter.write("server-" + (i + 1) + ": " + latecy
                            //                            + ", last_update: " + resultSet.getLong("last_update")
                            //                            + ", receive_time: " + resultSet.getLong("receive_time")
                            + ", from_where: " + resultSet.getLong("from_where")
                            + "\n");
                } else {
                    fileWriter.write("Server: " + (i + 1)
                            + ", last_update: " + resultSet.getLong("last_update")
                            + ", receive_time: " + resultSet.getLong("receive_time") + "\n");
                }
            }
            resultSet.close();
            for (int j = 0; j < CLIENTS_PER_SERVER; j++) {
//                String filename = DATABASE_PATH + "/server-" + (i + 1) + "-client-" + (j + 1) + ".db";
//                Connection connection = DriverManager.getConnection("jdbc:sqlite:" + filename);
//                String sql = "SELECT * FROM [message] WHERE [item_application_name] = ? AND [item_key] = ?;";
//                PreparedStatement statement = connection.prepareStatement(sql);
//                statement.setString(1, applicationName);
//                statement.setString(2, key);
//                ResultSet resultSet = statement.executeQuery();
                filename = DATABASE_PATH + "/server-" + (i + 1) + "-client-" + (j + 1) + ".db";
                connection = DriverManager.getConnection("jdbc:sqlite:" + filename);
                sql = "SELECT * FROM [message] WHERE [item_application_name] = ? AND [item_key] = ?;";
                statement = connection.prepareStatement(sql);
                statement.setString(1, applicationName);
                statement.setString(2, key);
                resultSet = statement.executeQuery();

                while (resultSet.next()) {
                    // latecyList.add(resultSet.getInt("last_update"));
                    int latecy = resultSet.getInt("latecy");
                    if (latecy > 0) {
                        latecyList.add(latecy);
                        fileWriter.write("client-" + (i + 1) + "-" + (j + 1) + ": " + latecy + "\n");
                    } else {
                        fileWriter.write("Server: " + (i + 1) + ", Client: " + (j + 1)
                                + ", last_update: " + resultSet.getLong("last_update")
                                + ", receive_time: " + resultSet.getLong("receive_time") + "\n");
                    }
                }
                resultSet.close();
            }
        }
        fileWriter.close();

        fileWriter = new FileWriter("data/latecy.txt");

        latecyList.sort((num1, num2) -> {
            return num1.compareTo(num2);
        });

        int averageLatecy = latecyList.stream().reduce(Integer::sum).orElse(0) / latecyList.size();
        fileWriter.write("average: " + averageLatecy + "\n");
        fileWriter.write("0.1: " + String.valueOf(latecyList.get((int) (latecyList.size() * 0.1))) + "\n");
        fileWriter.write("0.25: " + String.valueOf(latecyList.get((int) (latecyList.size() * 0.25))) + "\n");
        fileWriter.write("0.5: " + String.valueOf(latecyList.get((int) (latecyList.size() * 0.5))) + "\n");
        fileWriter.write("0.75: " + String.valueOf(latecyList.get((int) (latecyList.size() * 0.75))) + "\n");
        fileWriter.write("0.99: " + String.valueOf(latecyList.get((int) (latecyList.size() * 0.99))) + "\n");

        fileWriter.close();
    }
}
